Completed
Push — master ( 158ed8...34f194 )
by Alejandro
04:53 queued 02:19
created

VisitsParser.js ➔ ???   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 16
Code Lines 4

Duplication

Lines 16
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 6.5625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
nc 5
nop 1
dl 16
loc 16
ccs 6
cts 8
cp 0.75
crap 6.5625
rs 8.6666
c 1
b 0
f 0
eloc 4
1
import { isNil, isEmpty, memoizeWith, prop } from 'ramda';
2
3 1 View Code Duplication
const osFromUserAgent = (userAgent) => {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
4 5
  const lowerUserAgent = userAgent.toLowerCase();
5
6 5
  switch (true) {
7
    case lowerUserAgent.indexOf('linux') >= 0:
8 3
      return 'Linux';
9
    case lowerUserAgent.indexOf('windows') >= 0:
10 1
      return 'Windows';
11
    case lowerUserAgent.indexOf('mac') >= 0:
12 1
      return 'MacOS';
13
    case lowerUserAgent.indexOf('mobi') >= 0:
14
      return 'Mobile';
15
    default:
16
      return 'Others';
17
  }
18
};
19
20 1 View Code Duplication
const browserFromUserAgent = (userAgent) => {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
21 5
  const lowerUserAgent = userAgent.toLowerCase();
22
23 6
  switch (true) {
24
    case lowerUserAgent.indexOf('opera') >= 0 || lowerUserAgent.indexOf('opr') >= 0:
25 1
      return 'Opera';
26
    case lowerUserAgent.indexOf('firefox') >= 0:
27 2
      return 'Firefox';
28
    case lowerUserAgent.indexOf('chrome') >= 0:
29 2
      return 'Chrome';
30
    case lowerUserAgent.indexOf('safari') >= 0:
31
      return 'Safari';
32
    case lowerUserAgent.indexOf('msie') >= 0:
33
      return 'Internet Explorer';
34
    default:
35
      return 'Others';
36
  }
37
};
38
39 1
const extractDomain = (url) => {
40 3
  const domain = url.indexOf('://') > -1 ? url.split('/')[2] : url.split('/')[0];
41
42 3
  return domain.split(':')[0];
43
};
44
45 1
const visitLocationHasProperty = (visitLocation, propertyName) =>
46 15
  !isNil(visitLocation)
47
  && !isNil(visitLocation[propertyName])
48
  && !isEmpty(visitLocation[propertyName]);
49
50 1
const updateOsStatsForVisit = (osStats, { userAgent }) => {
51 5
  const os = isNil(userAgent) ? 'Others' : osFromUserAgent(userAgent);
52
53 5
  osStats[os] = (osStats[os] || 0) + 1;
54
};
55
56 1
const updateBrowsersStatsForVisit = (browsersStats, { userAgent }) => {
57 5
  const browser = isNil(userAgent) ? 'Others' : browserFromUserAgent(userAgent);
58
59 5
  browsersStats[browser] = (browsersStats[browser] || 0) + 1;
60
};
61
62 1
const updateReferrersStatsForVisit = (referrersStats, { referer }) => {
63 5
  const notHasDomain = isNil(referer) || isEmpty(referer);
64 5
  const domain = notHasDomain ? 'Unknown' : extractDomain(referer);
65
66 5
  referrersStats[domain] = (referrersStats[domain] || 0) + 1;
67
};
68
69 2
const updateLocationsStatsForVisit = (propertyName) => (stats, { visitLocation }) => {
70 10
  const hasLocationProperty = visitLocationHasProperty(visitLocation, propertyName);
71 10
  const value = hasLocationProperty ? visitLocation[propertyName] : 'Unknown';
72
73 10
  stats[value] = (stats[value] || 0) + 1;
74
};
75
76 1
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('countryName');
77 1
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('cityName');
78
79 1
const updateCitiesForMapForVisit = (citiesForMapStats, { visitLocation }) => {
80 5
  if (!visitLocationHasProperty(visitLocation, 'cityName')) {
81 2
    return;
82
  }
83
84 3
  const { cityName, latitude, longitude } = visitLocation;
85 3
  const currentCity = citiesForMapStats[cityName] || {
86
    cityName,
87
    count: 0,
88
    latLong: [ parseFloat(latitude), parseFloat(longitude) ],
89
  };
90
91 3
  currentCity.count++;
92
93 3
  citiesForMapStats[cityName] = currentCity;
94
};
95
96 1
export const processStatsFromVisits = memoizeWith(prop('id'), ({ visits }) =>
97 1
  visits.reduce(
98
    (stats, visit) => {
99
      // We mutate the original object because it has a big side effect when large data sets are processed
100 5
      updateOsStatsForVisit(stats.os, visit);
101 5
      updateBrowsersStatsForVisit(stats.browsers, visit);
102 5
      updateReferrersStatsForVisit(stats.referrers, visit);
103 5
      updateCountriesStatsForVisit(stats.countries, visit);
104 5
      updateCitiesStatsForVisit(stats.cities, visit);
105 5
      updateCitiesForMapForVisit(stats.citiesForMap, visit);
106
107 5
      return stats;
108
    },
109
    { os: {}, browsers: {}, referrers: {}, countries: {}, cities: {}, citiesForMap: {} }
110
  ));
111